
Apply suggested workaround for AMD CPU errata 665 Integer Divide Instruction May Cause Unpredictable Behavior

Affects (at least)chromium: https://bugs.chromium.org/p/chromium/issues/detail?id=599899#c27
With no665wo kernel cmdline(aka without this patch) the following video crashes in chromium: https://www.youtube.com/watch?v=hqKafI7Amd8

Chromiums tested:
 51.0.2704.19 (Developer Build) (64-bit)
 Revision  7ac91e6ac84fc4d63b4b5f1355fc94b40c9172b0

Chromium	55.0.2850.0 (Developer Build) (64-bit)
Revision	59aa6aab66c0a3c12644d44c686c02d484814da6-refs/heads/master@{#416472}



Kernels tested:
Linux gobaby 4.6.0-rc4 #9 SMP PREEMPT Tue Apr 26 01:41:26 EEST 2016 x86_64 AMD A6-3400M APU with Radeon(tm) HD Graphics AuthenticAMD GNU/Linux
Linux myzee 4.8.0-rc4-g9ca581b #92 SMP PREEMPT Sun Sep 4 19:25:38 CEST 2016 x86_64 GNU/Linux



diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index b81fe2d..d726900 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -669,15 +669,55 @@ static void init_amd_gh(struct cpuinfo_x86 *c)
 		set_cpu_bug(c, X86_BUG_AMD_TLB_MMATCH);
 }
 
+
+bool activate_665erratum = true;
+EXPORT_SYMBOL(activate_665erratum);
+
+static int __init oksomefunc(char *str)
+{
+	activate_665erratum = false;
+	return 0;
+}
+#define kernel_arg_for_disable665 "no665wo"
+early_param(kernel_arg_for_disable665, oksomefunc);
+
 #define MSR_AMD64_DE_CFG	0xC0011029
 
 static void init_amd_ln(struct cpuinfo_x86 *c)
 {
+  int err;
 	/*
-	 * Apply erratum 665 fix unconditionally so machines without a BIOS
+	 * Apply erratum 665 fix conditionally so machines without a BIOS
 	 * fix work.
 	 */
-	msr_set_bit(MSR_AMD64_DE_CFG, 31);
+  if (activate_665erratum) {
+    pr_info(FW_INFO "CPU: Setting workaround for AMD erratum 665 Integer Divide Instruction May Cause Unpredictable Behavior (set '%s' in /proc/cmdline to disable)\n", kernel_arg_for_disable665);
+    /* 665 Integer Divide Instruction May Cause Unpredictable Behavior
+     * Description
+     * Under a highly specific and detailed set of internal timing conditions, the processor core may abort a
+     * speculative DIV or IDIV integer divide instruction (due to the speculative execution being redirected,
+     * for example due to a mispredicted branch) but may hang or prematurely complete the first instruction
+     * of the non-speculative path.
+     * Potential Effect on System
+     * Unpredictable system behavior, usually resulting in a system hang.
+     * Suggested Workaround
+     * BIOS should set MSRC001_1029[31].
+     * This workaround alters the DIV/IDIV instruction latency specified in the Software Optimization
+     * Guide for AMD Family 10h and 12h Processors, order# 40546. With this workaround applied, the
+     * DIV/IDIV latency for AMD Family 12h Processors are similar to the DIV/IDIV latency for
+     * AMD Family 10h Processors.
+     * Fix Planned
+     * No
+     * src: page 45/53 of http://support.amd.com/us/Processor_TechDocs/44739_12h_Rev_Gd.pdf (which is a broken link currently, see the 2012 saved archive.org one)
+     */
+    err=msr_set_bit(MSR_AMD64_DE_CFG, 31);
+    if (err < 0) { //0=already set, 1=did set; <0 = error
+      pr_warn(FW_INFO "CPU: setting MSR failed for the 665 erratum workaround! err:%d", err);
+    }
+  } else {
+    pr_info(FW_INFO "CPU: not activating workaround for 665 due to kernel arg '%s' (see /proc/cmdline)\n", kernel_arg_for_disable665);
+  }
+
 }
 
 static void init_amd_bd(struct cpuinfo_x86 *c)
@@ -913,7 +953,6 @@ static const int amd_erratum_400[] =
 static const int amd_erratum_383[] =
 	AMD_OSVW_ERRATUM(3, AMD_MODEL_RANGE(0x10, 0, 0, 0xff, 0xf));
 
-
 static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum)
 {
 	int osvw_id = *erratum++;
